package middleware

import (
	"encoding/json"
	"fmt"
	"gitee.com/z930255076/go-ext/config"
	"gitee.com/z930255076/go-ext/constants"
	"gitee.com/z930255076/go-ext/database"
	"gitee.com/z930255076/go-ext/response"
	"github.com/gofiber/fiber/v2"
	"os"
	"time"
)

type LoginData struct {
	ID        int64  `json:"id"`
	Platform  string `json:"platform"`
	LoginTime int64  `json:"login_time"`
	LoginIp   string `json:"login_ip"`
}

type User struct {
	ID        int64  `json:"id"`
	NickName  string `json:"nick_name"`
	Account   string `json:"account"`
	RoleID    int64  `json:"role_id"`
	LastIp    string `json:"last_ip"`
	LastTime  int64  `json:"last_time"`
	CreatedAt int64  `json:"created_at"`
	UpdatedAt int64  `json:"updated_at"`
	DeletedAt int64  `json:"deleted_at"`
}

func LoginCheck(c *fiber.Ctx) error {
	token := c.Get("U-Token")
	if token == "" {
		return response.Error(c, fiber.NewError(constants.NeedLogin, "请登录"))
	}

	loginData, err := GetLoginData(token)
	if err != nil {
		return response.Error(c, err)
	}

	// 验证时效.
	if time.Now().Unix() > loginData.LoginTime+config.UserTokenTimeOut {
		return response.Error(c, fiber.NewError(constants.NeedLogin, "身份失效"))
	}

	// 验证ip
	ip := c.IP()
	if ip != loginData.LoginIp {
		return response.Error(c, fiber.NewError(constants.NeedLogin, "非法使用"))
	}

	// 获取用户信息.
	userInfo, err := GetUserInfo(loginData.ID)
	if err != nil {
		return response.Error(c, err)
	}

	c.Locals("userInfo", userInfo)

	return c.Next()
}

func GetLoginData(token string) (LoginData, error) {
	var loginData LoginData
	simpleUser := os.Getenv("SIMPLE_USER")
	key := fmt.Sprintf("%s:%s:%s", simpleUser, constants.TokenUser, token)
	jsonLoginData, err := database.Redis.Get(key).Result()
	if err != nil {
		return loginData, fiber.NewError(constants.NeedLogin, "未检测到登录信息")
	}

	if err := json.Unmarshal([]byte(jsonLoginData), &loginData); err != nil {
		return loginData, fiber.NewError(constants.NeedLogin, "登录信息解析失败")
	}

	return loginData, nil
}

func GetUserInfo(userID int64) (User, error) {
	var userInfo User
	simpleUser := os.Getenv("SIMPLE_USER")
	key := fmt.Sprintf("%s:%s:%d", simpleUser, constants.UserIdUser, userID)
	jsonUserInfo, err := database.Redis.Get(key).Result()
	if err != nil {
		return userInfo, fiber.NewError(constants.NeedLogin, "用户登录信息失效")
	}

	if err := json.Unmarshal([]byte(jsonUserInfo), &userInfo); err != nil {
		return userInfo, fiber.NewError(constants.NeedLogin, "用户登录信息解析失败")
	}

	return userInfo, nil
}
